<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>string.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_string_string.js.html">string.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
<a name="line2"></a>//
<a name="line3"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line4"></a>// you may not use this file except in compliance with the License.
<a name="line5"></a>// You may obtain a copy of the License at
<a name="line6"></a>//
<a name="line7"></a>//      http://www.apache.org/licenses/LICENSE-2.0
<a name="line8"></a>//
<a name="line9"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line10"></a>// distributed under the License is distributed on an &quot;AS-IS&quot; BASIS,
<a name="line11"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line12"></a>// See the License for the specific language governing permissions and
<a name="line13"></a>// limitations under the License.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Utilities for string manipulation.
<a name="line17"></a> */
<a name="line18"></a>
<a name="line19"></a>
<a name="line20"></a>/**
<a name="line21"></a> * Namespace for string utilities
<a name="line22"></a> */
<a name="line23"></a>goog.provide(&#39;goog.string&#39;);
<a name="line24"></a>goog.provide(&#39;goog.string.Unicode&#39;);
<a name="line25"></a>
<a name="line26"></a>
<a name="line27"></a>/**
<a name="line28"></a> * Common Unicode string characters.
<a name="line29"></a> * @enum {string}
<a name="line30"></a> */
<a name="line31"></a>goog.string.Unicode = {
<a name="line32"></a>  NBSP: &#39;\xa0&#39;
<a name="line33"></a>};
<a name="line34"></a>
<a name="line35"></a>
<a name="line36"></a>/**
<a name="line37"></a> * Fast prefix-checker.
<a name="line38"></a> * @param {string} str The string to check.
<a name="line39"></a> * @param {string} prefix A string to look for at the start of {@code str}.
<a name="line40"></a> * @return {boolean} True if {@code str} begins with {@code prefix}.
<a name="line41"></a> */
<a name="line42"></a>goog.string.startsWith = function(str, prefix) {
<a name="line43"></a>  return str.lastIndexOf(prefix, 0) == 0;
<a name="line44"></a>};
<a name="line45"></a>
<a name="line46"></a>
<a name="line47"></a>/**
<a name="line48"></a> * Fast suffix-checker.
<a name="line49"></a> * @param {string} str The string to check.
<a name="line50"></a> * @param {string} suffix A string to look for at the end of {@code str}.
<a name="line51"></a> * @return {boolean} True if {@code str} ends with {@code suffix}.
<a name="line52"></a> */
<a name="line53"></a>goog.string.endsWith = function(str, suffix) {
<a name="line54"></a>  var l = str.length - suffix.length;
<a name="line55"></a>  return l &gt;= 0 &amp;&amp; str.indexOf(suffix, l) == l;
<a name="line56"></a>};
<a name="line57"></a>
<a name="line58"></a>
<a name="line59"></a>/**
<a name="line60"></a> * Case-insensitive prefix-checker.
<a name="line61"></a> * @param {string} str The string to check.
<a name="line62"></a> * @param {string} prefix  A string to look for at the end of {@code str}.
<a name="line63"></a> * @return {boolean} True if {@code str} begins with {@code prefix} (ignoring
<a name="line64"></a> *     case).
<a name="line65"></a> */
<a name="line66"></a>goog.string.caseInsensitiveStartsWith = function(str, prefix) {
<a name="line67"></a>  return goog.string.caseInsensitiveCompare(
<a name="line68"></a>      prefix, str.substr(0, prefix.length)) == 0;
<a name="line69"></a>};
<a name="line70"></a>
<a name="line71"></a>
<a name="line72"></a>/**
<a name="line73"></a> * Case-insensitive suffix-checker.
<a name="line74"></a> * @param {string} str The string to check.
<a name="line75"></a> * @param {string} suffix A string to look for at the end of {@code str}.
<a name="line76"></a> * @return {boolean} True if {@code str} ends with {@code suffix} (ignoring
<a name="line77"></a> *     case).
<a name="line78"></a> */
<a name="line79"></a>goog.string.caseInsensitiveEndsWith = function(str, suffix) {
<a name="line80"></a>  return goog.string.caseInsensitiveCompare(
<a name="line81"></a>      suffix, str.substr(str.length - suffix.length, suffix.length)) == 0;
<a name="line82"></a>};
<a name="line83"></a>
<a name="line84"></a>
<a name="line85"></a>/**
<a name="line86"></a> * Does simple python-style string substitution.
<a name="line87"></a> * subs(&quot;foo%s hot%s&quot;, &quot;bar&quot;, &quot;dog&quot;) becomes &quot;foobar hotdog&quot;.
<a name="line88"></a> * @param {string} str The string containing the pattern.
<a name="line89"></a> * @param {...*} var_args The items to substitute into the pattern.
<a name="line90"></a> * @return {string} A copy of {@code str} in which each occurrence of
<a name="line91"></a> *     {@code %s} has been replaced an argument from {@code var_args}.
<a name="line92"></a> */
<a name="line93"></a>goog.string.subs = function(str, var_args) {
<a name="line94"></a>  // This appears to be slow, but testing shows it compares more or less
<a name="line95"></a>  // equivalent to the regex.exec method.
<a name="line96"></a>  for (var i = 1; i &lt; arguments.length; i++) {
<a name="line97"></a>    // We cast to String in case an argument is a Function.  Replacing $&amp;, for
<a name="line98"></a>    // example, with $$$&amp; stops the replace from subsituting the whole match
<a name="line99"></a>    // into the resultant string.  $$$&amp; in the first replace becomes $$&amp; in the
<a name="line100"></a>    //  second, which leaves $&amp; in the resultant string.  Also:
<a name="line101"></a>    // $$, $`, $&#39;, $n $nn
<a name="line102"></a>    var replacement = String(arguments[i]).replace(/\$/g, &#39;$$$$&#39;);
<a name="line103"></a>    str = str.replace(/\%s/, replacement);
<a name="line104"></a>  }
<a name="line105"></a>  return str;
<a name="line106"></a>};
<a name="line107"></a>
<a name="line108"></a>
<a name="line109"></a>/**
<a name="line110"></a> * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines
<a name="line111"></a> * and tabs) to a single space, and strips leading and trailing whitespace.
<a name="line112"></a> * @param {string} str Input string.
<a name="line113"></a> * @return {string} A copy of {@code str} with collapsed whitespace.
<a name="line114"></a> */
<a name="line115"></a>goog.string.collapseWhitespace = function(str) {
<a name="line116"></a>  // Since IE doesn&#39;t include non-breaking-space (0xa0) in their \s character
<a name="line117"></a>  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
<a name="line118"></a>  // include it in the regexp to enforce consistent cross-browser behavior.
<a name="line119"></a>  return str.replace(/[\s\xa0]+/g, &#39; &#39;).replace(/^\s+|\s+$/g, &#39;&#39;);
<a name="line120"></a>};
<a name="line121"></a>
<a name="line122"></a>
<a name="line123"></a>/**
<a name="line124"></a> * Checks if a string is empty or contains only whitespaces.
<a name="line125"></a> * @param {string} str The string to check.
<a name="line126"></a> * @return {boolean} True if {@code str} is empty or whitespace only.
<a name="line127"></a> */
<a name="line128"></a>goog.string.isEmpty = function(str) {
<a name="line129"></a>  // testing length == 0 first is actually slower in all browsers (about the
<a name="line130"></a>  // same in Opera).
<a name="line131"></a>  // Since IE doesn&#39;t include non-breaking-space (0xa0) in their \s character
<a name="line132"></a>  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
<a name="line133"></a>  // include it in the regexp to enforce consistent cross-browser behavior.
<a name="line134"></a>  return /^[\s\xa0]*$/.test(str);
<a name="line135"></a>};
<a name="line136"></a>
<a name="line137"></a>
<a name="line138"></a>/**
<a name="line139"></a> * Checks if a string is null, undefined, empty or contains only whitespaces.
<a name="line140"></a> * @param {*} str The string to check.
<a name="line141"></a> * @return {boolean} True if{@code str} is null, undefined, empty, or
<a name="line142"></a> *     whitespace only.
<a name="line143"></a> */
<a name="line144"></a>goog.string.isEmptySafe = function(str) {
<a name="line145"></a>  return goog.string.isEmpty(goog.string.makeSafe(str));
<a name="line146"></a>};
<a name="line147"></a>
<a name="line148"></a>
<a name="line149"></a>/**
<a name="line150"></a> * Checks if a string is all breaking whitespace.
<a name="line151"></a> * @param {string} str The string to check.
<a name="line152"></a> * @return {boolean} Whether the string is all breaking whitespace.
<a name="line153"></a> */
<a name="line154"></a>goog.string.isBreakingWhitespace = function(str) {
<a name="line155"></a>  return !/[^\t\n\r ]/.test(str);
<a name="line156"></a>};
<a name="line157"></a>
<a name="line158"></a>
<a name="line159"></a>/**
<a name="line160"></a> * Checks if a string contains all letters.
<a name="line161"></a> * @param {string} str string to check.
<a name="line162"></a> * @return {boolean} True if {@code str} consists entirely of letters.
<a name="line163"></a> */
<a name="line164"></a>goog.string.isAlpha = function(str) {
<a name="line165"></a>  return !/[^a-zA-Z]/.test(str);
<a name="line166"></a>};
<a name="line167"></a>
<a name="line168"></a>
<a name="line169"></a>/**
<a name="line170"></a> * Checks if a string contains only numbers.
<a name="line171"></a> * @param {*} str string to check. If not a string, it will be
<a name="line172"></a> *     casted to one.
<a name="line173"></a> * @return {boolean} True if {@code str} is numeric.
<a name="line174"></a> */
<a name="line175"></a>goog.string.isNumeric = function(str) {
<a name="line176"></a>  return !/[^0-9]/.test(str);
<a name="line177"></a>};
<a name="line178"></a>
<a name="line179"></a>
<a name="line180"></a>/**
<a name="line181"></a> * Checks if a string contains only numbers or letters.
<a name="line182"></a> * @param {string} str string to check.
<a name="line183"></a> * @return {boolean} True if {@code str} is alphanumeric.
<a name="line184"></a> */
<a name="line185"></a>goog.string.isAlphaNumeric = function(str) {
<a name="line186"></a>  return !/[^a-zA-Z0-9]/.test(str);
<a name="line187"></a>};
<a name="line188"></a>
<a name="line189"></a>
<a name="line190"></a>/**
<a name="line191"></a> * Checks if a character is a space character.
<a name="line192"></a> * @param {string} ch Character to check.
<a name="line193"></a> * @return {boolean} True if {code ch} is a space.
<a name="line194"></a> */
<a name="line195"></a>goog.string.isSpace = function(ch) {
<a name="line196"></a>  return ch == &#39; &#39;;
<a name="line197"></a>};
<a name="line198"></a>
<a name="line199"></a>
<a name="line200"></a>/**
<a name="line201"></a> * Checks if a character is a valid unicode character.
<a name="line202"></a> * @param {string} ch Character to check.
<a name="line203"></a> * @return {boolean} True if {code ch} is a valid unicode character.
<a name="line204"></a> */
<a name="line205"></a>goog.string.isUnicodeChar = function(ch) {
<a name="line206"></a>  return ch.length == 1 &amp;&amp; ch &gt;= &#39; &#39; &amp;&amp; ch &lt;= &#39;~&#39; ||
<a name="line207"></a>         ch &gt;= &#39;\u0080&#39; &amp;&amp; ch &lt;= &#39;\uFFFD&#39;;
<a name="line208"></a>};
<a name="line209"></a>
<a name="line210"></a>
<a name="line211"></a>/**
<a name="line212"></a> * Takes a string and replaces newlines with a space. Multiple lines are
<a name="line213"></a> * replaced with a single space.
<a name="line214"></a> * @param {string} str The string from which to strip newlines.
<a name="line215"></a> * @return {string} A copy of {@code str} stripped of newlines.
<a name="line216"></a> */
<a name="line217"></a>goog.string.stripNewlines = function(str) {
<a name="line218"></a>  return str.replace(/(\r\n|\r|\n)+/g, &#39; &#39;);
<a name="line219"></a>};
<a name="line220"></a>
<a name="line221"></a>
<a name="line222"></a>/**
<a name="line223"></a> * Replaces Windows and Mac new lines with unix style: \r or \r\n with \n.
<a name="line224"></a> * @param {string} str The string to in which to canonicalize newlines.
<a name="line225"></a> * @return {string} {@code str} A copy of {@code} with canonicalized newlines.
<a name="line226"></a> */
<a name="line227"></a>goog.string.canonicalizeNewlines = function(str) {
<a name="line228"></a>  return str.replace(/(\r\n|\r|\n)/g, &#39;\n&#39;);
<a name="line229"></a>};
<a name="line230"></a>
<a name="line231"></a>
<a name="line232"></a>/**
<a name="line233"></a> * Normalizes whitespace in a string, replacing all whitespace chars with
<a name="line234"></a> * a space.
<a name="line235"></a> * @param {string} str The string in which to normalize whitespace.
<a name="line236"></a> * @return {string} A copy of {@code str} with all whitespace normalized.
<a name="line237"></a> */
<a name="line238"></a>goog.string.normalizeWhitespace = function(str) {
<a name="line239"></a>  return str.replace(/\xa0|\s/g, &#39; &#39;);
<a name="line240"></a>};
<a name="line241"></a>
<a name="line242"></a>
<a name="line243"></a>/**
<a name="line244"></a> * Normalizes spaces in a string, replacing all consecutive spaces and tabs
<a name="line245"></a> * with a single space. Replaces non-breaking space with a space.
<a name="line246"></a> * @param {string} str The string in which to normalize spaces.
<a name="line247"></a> * @return {string} A copy of {@code str} with all consecutive spaces and tabs
<a name="line248"></a> *    replaced with a single space.
<a name="line249"></a> */
<a name="line250"></a>goog.string.normalizeSpaces = function(str) {
<a name="line251"></a>  return str.replace(/\xa0|[ \t]+/g, &#39; &#39;);
<a name="line252"></a>};
<a name="line253"></a>
<a name="line254"></a>
<a name="line255"></a>/**
<a name="line256"></a> * Removes the breaking spaces from the left and right of the string and
<a name="line257"></a> * collapses the sequences of breaking spaces in the middle into single spaces.
<a name="line258"></a> * The original and the result strings render the same way in HTML.
<a name="line259"></a> * @param {string} str A string in which to collapse spaces.
<a name="line260"></a> * @return {string} Copy of the string with normalized breaking spaces.
<a name="line261"></a> */
<a name="line262"></a>goog.string.collapseBreakingSpaces = function(str) {
<a name="line263"></a>  return str.replace(/[\t\r\n ]+/g, &#39; &#39;).replace(
<a name="line264"></a>      /^[\t\r\n ]+|[\t\r\n ]+$/g, &#39;&#39;);
<a name="line265"></a>};
<a name="line266"></a>
<a name="line267"></a>
<a name="line268"></a>/**
<a name="line269"></a> * Trims white spaces to the left and right of a string.
<a name="line270"></a> * @param {string} str The string to trim.
<a name="line271"></a> * @return {string} A trimmed copy of {@code str}.
<a name="line272"></a> */
<a name="line273"></a>goog.string.trim = function(str) {
<a name="line274"></a>  // Since IE doesn&#39;t include non-breaking-space (0xa0) in their \s character
<a name="line275"></a>  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
<a name="line276"></a>  // include it in the regexp to enforce consistent cross-browser behavior.
<a name="line277"></a>  return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, &#39;&#39;);
<a name="line278"></a>};
<a name="line279"></a>
<a name="line280"></a>
<a name="line281"></a>/**
<a name="line282"></a> * Trims whitespaces at the left end of a string.
<a name="line283"></a> * @param {string} str The string to left trim.
<a name="line284"></a> * @return {string} A trimmed copy of {@code str}.
<a name="line285"></a> */
<a name="line286"></a>goog.string.trimLeft = function(str) {
<a name="line287"></a>  // Since IE doesn&#39;t include non-breaking-space (0xa0) in their \s character
<a name="line288"></a>  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
<a name="line289"></a>  // include it in the regexp to enforce consistent cross-browser behavior.
<a name="line290"></a>  return str.replace(/^[\s\xa0]+/, &#39;&#39;);
<a name="line291"></a>};
<a name="line292"></a>
<a name="line293"></a>
<a name="line294"></a>/**
<a name="line295"></a> * Trims whitespaces at the right end of a string.
<a name="line296"></a> * @param {string} str The string to right trim.
<a name="line297"></a> * @return {string} A trimmed copy of {@code str}.
<a name="line298"></a> */
<a name="line299"></a>goog.string.trimRight = function(str) {
<a name="line300"></a>  // Since IE doesn&#39;t include non-breaking-space (0xa0) in their \s character
<a name="line301"></a>  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
<a name="line302"></a>  // include it in the regexp to enforce consistent cross-browser behavior.
<a name="line303"></a>  return str.replace(/[\s\xa0]+$/, &#39;&#39;);
<a name="line304"></a>};
<a name="line305"></a>
<a name="line306"></a>
<a name="line307"></a>/**
<a name="line308"></a> * A string comparator that ignores case.
<a name="line309"></a> * -1 = str1 less than str2
<a name="line310"></a> *  0 = str1 equals str2
<a name="line311"></a> *  1 = str1 greater than str2
<a name="line312"></a> *
<a name="line313"></a> * @param {string} str1 The string to compare.
<a name="line314"></a> * @param {string} str2 The string to compare {@code str1} to.
<a name="line315"></a> * @return {number} The comparator result, as described above.
<a name="line316"></a> */
<a name="line317"></a>goog.string.caseInsensitiveCompare = function(str1, str2) {
<a name="line318"></a>  var test1 = String(str1).toLowerCase();
<a name="line319"></a>  var test2 = String(str2).toLowerCase();
<a name="line320"></a>
<a name="line321"></a>  if (test1 &lt; test2) {
<a name="line322"></a>    return -1;
<a name="line323"></a>  } else if (test1 == test2) {
<a name="line324"></a>    return 0;
<a name="line325"></a>  } else {
<a name="line326"></a>    return 1;
<a name="line327"></a>  }
<a name="line328"></a>};
<a name="line329"></a>
<a name="line330"></a>
<a name="line331"></a>/**
<a name="line332"></a> * Regular expression used for splitting a string into substrings of fractional
<a name="line333"></a> * numbers, integers, and non-numeric characters.
<a name="line334"></a> * @type {RegExp}
<a name="line335"></a> * @private
<a name="line336"></a> */
<a name="line337"></a>goog.string.numerateCompareRegExp_ = /(\.\d+)|(\d+)|(\D+)/g;
<a name="line338"></a>
<a name="line339"></a>
<a name="line340"></a>/**
<a name="line341"></a> * String comparison function that handles numbers in a way humans might expect.
<a name="line342"></a> * Using this function, the string &quot;File 2.jpg&quot; sorts before &quot;File 10.jpg&quot;. The
<a name="line343"></a> * comparison is mostly case-insensitive, though strings that are identical
<a name="line344"></a> * except for case are sorted with the upper-case strings before lower-case.
<a name="line345"></a> *
<a name="line346"></a> * This comparison function is significantly slower (about 500x) than either
<a name="line347"></a> * the default or the case-insensitive compare. It should not be used in
<a name="line348"></a> * time-critical code, but should be fast enough to sort several hundred short
<a name="line349"></a> * strings (like filenames) with a reasonable delay.
<a name="line350"></a> *
<a name="line351"></a> * @param {string} str1 The string to compare in a numerically sensitive way.
<a name="line352"></a> * @param {string} str2 The string to compare {@code str1} to.
<a name="line353"></a> * @return {number} less than 0 if str1 &lt; str2, 0 if str1 == str2, greater than
<a name="line354"></a> *     0 if str1 &gt; str2.
<a name="line355"></a> */
<a name="line356"></a>goog.string.numerateCompare = function(str1, str2) {
<a name="line357"></a>  if (str1 == str2) {
<a name="line358"></a>    return 0;
<a name="line359"></a>  }
<a name="line360"></a>  if (!str1) {
<a name="line361"></a>    return -1;
<a name="line362"></a>  }
<a name="line363"></a>  if (!str2) {
<a name="line364"></a>    return 1;
<a name="line365"></a>  }
<a name="line366"></a>
<a name="line367"></a>  // Using match to split the entire string ahead of time turns out to be faster
<a name="line368"></a>  // for most inputs than using RegExp.exec or iterating over each character.
<a name="line369"></a>  var tokens1 = str1.toLowerCase().match(goog.string.numerateCompareRegExp_);
<a name="line370"></a>  var tokens2 = str2.toLowerCase().match(goog.string.numerateCompareRegExp_);
<a name="line371"></a>
<a name="line372"></a>  var count = Math.min(tokens1.length, tokens2.length);
<a name="line373"></a>
<a name="line374"></a>  for (var i = 0; i &lt; count; i++) {
<a name="line375"></a>    var a = tokens1[i];
<a name="line376"></a>    var b = tokens2[i];
<a name="line377"></a>
<a name="line378"></a>    // Compare pairs of tokens, returning if one token sorts before the other.
<a name="line379"></a>    if (a != b) {
<a name="line380"></a>
<a name="line381"></a>      // Only if both tokens are integers is a special comparison required.
<a name="line382"></a>      // Decimal numbers are sorted as strings (e.g., &#39;.09&#39; &lt; &#39;.1&#39;).
<a name="line383"></a>      var num1 = parseInt(a, 10);
<a name="line384"></a>      if (!isNaN(num1)) {
<a name="line385"></a>        var num2 = parseInt(b, 10);
<a name="line386"></a>        if (!isNaN(num2) &amp;&amp; num1 - num2) {
<a name="line387"></a>          return num1 - num2;
<a name="line388"></a>        }
<a name="line389"></a>      }
<a name="line390"></a>      return a &lt; b ? -1 : 1;
<a name="line391"></a>    }
<a name="line392"></a>  }
<a name="line393"></a>
<a name="line394"></a>  // If one string is a substring of the other, the shorter string sorts first.
<a name="line395"></a>  if (tokens1.length != tokens2.length) {
<a name="line396"></a>    return tokens1.length - tokens2.length;
<a name="line397"></a>  }
<a name="line398"></a>
<a name="line399"></a>  // The two strings must be equivalent except for case (perfect equality is
<a name="line400"></a>  // tested at the head of the function.) Revert to default ASCII-betical string
<a name="line401"></a>  // comparison to stablize the sort.
<a name="line402"></a>  return str1 &lt; str2 ? -1 : 1;
<a name="line403"></a>};
<a name="line404"></a>
<a name="line405"></a>
<a name="line406"></a>/**
<a name="line407"></a> * URL-encodes a string
<a name="line408"></a> * @param {*} str The string to url-encode.
<a name="line409"></a> * @return {string} An encoded copy of {@code str} that is safe for urls.
<a name="line410"></a> *     Note that &#39;#&#39;, &#39;:&#39;, and other characters used to delimit portions
<a name="line411"></a> *     of URLs *will* be encoded.
<a name="line412"></a> */
<a name="line413"></a>goog.string.urlEncode = function(str) {
<a name="line414"></a>  return encodeURIComponent(String(str));
<a name="line415"></a>};
<a name="line416"></a>
<a name="line417"></a>
<a name="line418"></a>/**
<a name="line419"></a> * URL-decodes the string. We need to specially handle &#39;+&#39;s because
<a name="line420"></a> * the javascript library doesn&#39;t convert them to spaces.
<a name="line421"></a> * @param {string} str The string to url decode.
<a name="line422"></a> * @return {string} The decoded {@code str}.
<a name="line423"></a> */
<a name="line424"></a>goog.string.urlDecode = function(str) {
<a name="line425"></a>  return decodeURIComponent(str.replace(/\+/g, &#39; &#39;));
<a name="line426"></a>};
<a name="line427"></a>
<a name="line428"></a>
<a name="line429"></a>/**
<a name="line430"></a> * Converts \n to &lt;br&gt;s or &lt;br /&gt;s.
<a name="line431"></a> * @param {string} str The string in which to convert newlines.
<a name="line432"></a> * @param {boolean=} opt_xml Whether to use XML compatible tags.
<a name="line433"></a> * @return {string} A copy of {@code str} with converted newlines.
<a name="line434"></a> */
<a name="line435"></a>goog.string.newLineToBr = function(str, opt_xml) {
<a name="line436"></a>  return str.replace(/(\r\n|\r|\n)/g, opt_xml ? &#39;&lt;br /&gt;&#39; : &#39;&lt;br&gt;&#39;);
<a name="line437"></a>};
<a name="line438"></a>
<a name="line439"></a>
<a name="line440"></a>/**
<a name="line441"></a> * Escape double quote &#39;&quot;&#39; characters in addition to &#39;&amp;&#39;, &#39;&lt;&#39;, and &#39;&gt;&#39; so that a
<a name="line442"></a> * string can be included in an HTML tag attribute value within double quotes.
<a name="line443"></a> *
<a name="line444"></a> * It should be noted that &gt; doesn&#39;t need to be escaped for the HTML or XML to
<a name="line445"></a> * be valid, but it has been decided to escape it for consistency with other
<a name="line446"></a> * implementations.
<a name="line447"></a> *
<a name="line448"></a> * NOTE(user):
<a name="line449"></a> * HtmlEscape is often called during the generation of large blocks of HTML.
<a name="line450"></a> * Using statics for the regular expressions and strings is an optimization
<a name="line451"></a> * that can more than half the amount of time IE spends in this function for
<a name="line452"></a> * large apps, since strings and regexes both contribute to GC allocations.
<a name="line453"></a> *
<a name="line454"></a> * Testing for the presence of a character before escaping increases the number
<a name="line455"></a> * of function calls, but actually provides a speed increase for the average
<a name="line456"></a> * case -- since the average case often doesn&#39;t require the escaping of all 4
<a name="line457"></a> * characters and indexOf() is much cheaper than replace().
<a name="line458"></a> * The worst case does suffer slightly from the additional calls, therefore the
<a name="line459"></a> * opt_isLikelyToContainHtmlChars option has been included for situations
<a name="line460"></a> * where all 4 HTML entities are very likely to be present and need escaping.
<a name="line461"></a> *
<a name="line462"></a> * Some benchmarks (times tended to fluctuate +-0.05ms):
<a name="line463"></a> *                                     FireFox                     IE6
<a name="line464"></a> * (no chars / average (mix of cases) / all 4 chars)
<a name="line465"></a> * no checks                     0.13 / 0.22 / 0.22         0.23 / 0.53 / 0.80
<a name="line466"></a> * indexOf                       0.08 / 0.17 / 0.26         0.22 / 0.54 / 0.84
<a name="line467"></a> * indexOf + re test             0.07 / 0.17 / 0.28         0.19 / 0.50 / 0.85
<a name="line468"></a> *
<a name="line469"></a> * An additional advantage of checking if replace actually needs to be called
<a name="line470"></a> * is a reduction in the number of object allocations, so as the size of the
<a name="line471"></a> * application grows the difference between the various methods would increase.
<a name="line472"></a> *
<a name="line473"></a> * @param {string} str string to be escaped.
<a name="line474"></a> * @param {boolean=} opt_isLikelyToContainHtmlChars Don&#39;t perform a check to see
<a name="line475"></a> *     if the character needs replacing - use this option if you expect each of
<a name="line476"></a> *     the characters to appear often. Leave false if you expect few html
<a name="line477"></a> *     characters to occur in your strings, such as if you are escaping HTML.
<a name="line478"></a> * @return {string} An escaped copy of {@code str}.
<a name="line479"></a> */
<a name="line480"></a>goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
<a name="line481"></a>
<a name="line482"></a>  if (opt_isLikelyToContainHtmlChars) {
<a name="line483"></a>    return str.replace(goog.string.amperRe_, &#39;&amp;amp;&#39;)
<a name="line484"></a>          .replace(goog.string.ltRe_, &#39;&amp;lt;&#39;)
<a name="line485"></a>          .replace(goog.string.gtRe_, &#39;&amp;gt;&#39;)
<a name="line486"></a>          .replace(goog.string.quotRe_, &#39;&amp;quot;&#39;);
<a name="line487"></a>
<a name="line488"></a>  } else {
<a name="line489"></a>    // quick test helps in the case when there are no chars to replace, in
<a name="line490"></a>    // worst case this makes barely a difference to the time taken
<a name="line491"></a>    if (!goog.string.allRe_.test(str)) return str;
<a name="line492"></a>
<a name="line493"></a>    // str.indexOf is faster than regex.test in this case
<a name="line494"></a>    if (str.indexOf(&#39;&amp;&#39;) != -1) {
<a name="line495"></a>      str = str.replace(goog.string.amperRe_, &#39;&amp;amp;&#39;);
<a name="line496"></a>    }
<a name="line497"></a>    if (str.indexOf(&#39;&lt;&#39;) != -1) {
<a name="line498"></a>      str = str.replace(goog.string.ltRe_, &#39;&amp;lt;&#39;);
<a name="line499"></a>    }
<a name="line500"></a>    if (str.indexOf(&#39;&gt;&#39;) != -1) {
<a name="line501"></a>      str = str.replace(goog.string.gtRe_, &#39;&amp;gt;&#39;);
<a name="line502"></a>    }
<a name="line503"></a>    if (str.indexOf(&#39;&quot;&#39;) != -1) {
<a name="line504"></a>      str = str.replace(goog.string.quotRe_, &#39;&amp;quot;&#39;);
<a name="line505"></a>    }
<a name="line506"></a>    return str;
<a name="line507"></a>  }
<a name="line508"></a>};
<a name="line509"></a>
<a name="line510"></a>
<a name="line511"></a>/**
<a name="line512"></a> * Regular expression that matches an ampersand, for use in escaping.
<a name="line513"></a> * @type {RegExp}
<a name="line514"></a> * @private
<a name="line515"></a> */
<a name="line516"></a>goog.string.amperRe_ = /&amp;/g;
<a name="line517"></a>
<a name="line518"></a>
<a name="line519"></a>/**
<a name="line520"></a> * Regular expression that matches a less than sign, for use in escaping.
<a name="line521"></a> * @type {RegExp}
<a name="line522"></a> * @private
<a name="line523"></a> */
<a name="line524"></a>goog.string.ltRe_ = /&lt;/g;
<a name="line525"></a>
<a name="line526"></a>
<a name="line527"></a>/**
<a name="line528"></a> * Regular expression that matches a greater than sign, for use in escaping.
<a name="line529"></a> * @type {RegExp}
<a name="line530"></a> * @private
<a name="line531"></a> */
<a name="line532"></a>goog.string.gtRe_ = /&gt;/g;
<a name="line533"></a>
<a name="line534"></a>
<a name="line535"></a>/**
<a name="line536"></a> * Regular expression that matches a double quote, for use in escaping.
<a name="line537"></a> * @type {RegExp}
<a name="line538"></a> * @private
<a name="line539"></a> */
<a name="line540"></a>goog.string.quotRe_ = /\&quot;/g;
<a name="line541"></a>
<a name="line542"></a>
<a name="line543"></a>/**
<a name="line544"></a> * Regular expression that matches any character that needs to be escaped.
<a name="line545"></a> * @type {RegExp}
<a name="line546"></a> * @private
<a name="line547"></a> */
<a name="line548"></a>goog.string.allRe_ = /[&amp;&lt;&gt;\&quot;]/;
<a name="line549"></a>
<a name="line550"></a>
<a name="line551"></a>/**
<a name="line552"></a> * Unescapes an HTML string.
<a name="line553"></a> *
<a name="line554"></a> * @param {string} str The string to unescape.
<a name="line555"></a> * @return {string} An unescaped copy of {@code str}.
<a name="line556"></a> */
<a name="line557"></a>goog.string.unescapeEntities = function(str) {
<a name="line558"></a>  if (goog.string.contains(str, &#39;&amp;&#39;)) {
<a name="line559"></a>    // We are careful not to use a DOM if we do not have one. We use the []
<a name="line560"></a>    // notation so that the JSCompiler will not complain about these objects and
<a name="line561"></a>    // fields in the case where we have no DOM.
<a name="line562"></a>    if (&#39;document&#39; in goog.global) {
<a name="line563"></a>      return goog.string.unescapeEntitiesUsingDom_(str);
<a name="line564"></a>    } else {
<a name="line565"></a>      // Fall back on pure XML entities
<a name="line566"></a>      return goog.string.unescapePureXmlEntities_(str);
<a name="line567"></a>    }
<a name="line568"></a>  }
<a name="line569"></a>  return str;
<a name="line570"></a>};
<a name="line571"></a>
<a name="line572"></a>
<a name="line573"></a>/**
<a name="line574"></a> * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric
<a name="line575"></a> * entities. This function is XSS-safe and whitespace-preserving.
<a name="line576"></a> * @private
<a name="line577"></a> * @param {string} str The string to unescape.
<a name="line578"></a> * @return {string} The unescaped {@code str} string.
<a name="line579"></a> */
<a name="line580"></a>goog.string.unescapeEntitiesUsingDom_ = function(str) {
<a name="line581"></a>  var seen = {&#39;&amp;amp;&#39;: &#39;&amp;&#39;, &#39;&amp;lt;&#39;: &#39;&lt;&#39;, &#39;&amp;gt;&#39;: &#39;&gt;&#39;, &#39;&amp;quot;&#39;: &#39;&quot;&#39;};
<a name="line582"></a>  var div = document.createElement(&#39;div&#39;);
<a name="line583"></a>  // Match as many valid entity characters as possible. If the actual entity
<a name="line584"></a>  // happens to be shorter, it will still work as innerHTML will return the
<a name="line585"></a>  // trailing characters unchanged. Since the entity characters do not include
<a name="line586"></a>  // open angle bracket, there is no chance of XSS from the innerHTML use.
<a name="line587"></a>  // Since no whitespace is passed to innerHTML, whitespace is preserved.
<a name="line588"></a>  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {
<a name="line589"></a>    // Check for cached entity.
<a name="line590"></a>    var value = seen[s];
<a name="line591"></a>    if (value) {
<a name="line592"></a>      return value;
<a name="line593"></a>    }
<a name="line594"></a>    // Check for numeric entity.
<a name="line595"></a>    if (entity.charAt(0) == &#39;#&#39;) {
<a name="line596"></a>      // Prefix with 0 so that hex entities (e.g. &amp;#x10) parse as hex numbers.
<a name="line597"></a>      var n = Number(&#39;0&#39; + entity.substr(1));
<a name="line598"></a>      if (!isNaN(n)) {
<a name="line599"></a>        value = String.fromCharCode(n);
<a name="line600"></a>      }
<a name="line601"></a>    }
<a name="line602"></a>    // Fall back to innerHTML otherwise.
<a name="line603"></a>    if (!value) {
<a name="line604"></a>      // Append a non-entity character to avoid a bug in Webkit that parses
<a name="line605"></a>      // an invalid entity at the end of innerHTML text as the empty string.
<a name="line606"></a>      div.innerHTML = s + &#39; &#39;;
<a name="line607"></a>      // Then remove the trailing character from the result.
<a name="line608"></a>      value = div.firstChild.nodeValue.slice(0, -1);
<a name="line609"></a>    }
<a name="line610"></a>    // Cache and return.
<a name="line611"></a>    return seen[s] = value;
<a name="line612"></a>  });
<a name="line613"></a>};
<a name="line614"></a>
<a name="line615"></a>
<a name="line616"></a>/**
<a name="line617"></a> * Unescapes XML entities.
<a name="line618"></a> * @private
<a name="line619"></a> * @param {string} str The string to unescape.
<a name="line620"></a> * @return {string} An unescaped copy of {@code str}.
<a name="line621"></a> */
<a name="line622"></a>goog.string.unescapePureXmlEntities_ = function(str) {
<a name="line623"></a>  return str.replace(/&amp;([^;]+);/g, function(s, entity) {
<a name="line624"></a>    switch (entity) {
<a name="line625"></a>      case &#39;amp&#39;:
<a name="line626"></a>        return &#39;&amp;&#39;;
<a name="line627"></a>      case &#39;lt&#39;:
<a name="line628"></a>        return &#39;&lt;&#39;;
<a name="line629"></a>      case &#39;gt&#39;:
<a name="line630"></a>        return &#39;&gt;&#39;;
<a name="line631"></a>      case &#39;quot&#39;:
<a name="line632"></a>        return &#39;&quot;&#39;;
<a name="line633"></a>      default:
<a name="line634"></a>        if (entity.charAt(0) == &#39;#&#39;) {
<a name="line635"></a>          // Prefix with 0 so that hex entities (e.g. &amp;#x10) parse as hex.
<a name="line636"></a>          var n = Number(&#39;0&#39; + entity.substr(1));
<a name="line637"></a>          if (!isNaN(n)) {
<a name="line638"></a>            return String.fromCharCode(n);
<a name="line639"></a>          }
<a name="line640"></a>        }
<a name="line641"></a>        // For invalid entities we just return the entity
<a name="line642"></a>        return s;
<a name="line643"></a>    }
<a name="line644"></a>  });
<a name="line645"></a>};
<a name="line646"></a>
<a name="line647"></a>
<a name="line648"></a>/**
<a name="line649"></a> * Regular expression that matches an HTML entity.
<a name="line650"></a> * See also HTML5: Tokenization / Tokenizing character references.
<a name="line651"></a> * @private
<a name="line652"></a> * @type {!RegExp}
<a name="line653"></a> */
<a name="line654"></a>goog.string.HTML_ENTITY_PATTERN_ = /&amp;([^;\s&lt;&amp;]+);?/g;
<a name="line655"></a>
<a name="line656"></a>
<a name="line657"></a>/**
<a name="line658"></a> * Do escaping of whitespace to preserve spatial formatting. We use character
<a name="line659"></a> * entity #160 to make it safer for xml.
<a name="line660"></a> * @param {string} str The string in which to escape whitespace.
<a name="line661"></a> * @param {boolean=} opt_xml Whether to use XML compatible tags.
<a name="line662"></a> * @return {string} An escaped copy of {@code str}.
<a name="line663"></a> */
<a name="line664"></a>goog.string.whitespaceEscape = function(str, opt_xml) {
<a name="line665"></a>  return goog.string.newLineToBr(str.replace(/  /g, &#39; &amp;#160;&#39;), opt_xml);
<a name="line666"></a>};
<a name="line667"></a>
<a name="line668"></a>
<a name="line669"></a>/**
<a name="line670"></a> * Strip quote characters around a string.  The second argument is a string of
<a name="line671"></a> * characters to treat as quotes.  This can be a single character or a string of
<a name="line672"></a> * multiple character and in that case each of those are treated as possible
<a name="line673"></a> * quote characters. For example:
<a name="line674"></a> *
<a name="line675"></a> * &lt;pre&gt;
<a name="line676"></a> * goog.string.stripQuotes(&#39;&quot;abc&quot;&#39;, &#39;&quot;`&#39;) --&gt; &#39;abc&#39;
<a name="line677"></a> * goog.string.stripQuotes(&#39;`abc`&#39;, &#39;&quot;`&#39;) --&gt; &#39;abc&#39;
<a name="line678"></a> * &lt;/pre&gt;
<a name="line679"></a> *
<a name="line680"></a> * @param {string} str The string to strip.
<a name="line681"></a> * @param {string} quoteChars The quote characters to strip.
<a name="line682"></a> * @return {string} A copy of {@code str} without the quotes.
<a name="line683"></a> */
<a name="line684"></a>goog.string.stripQuotes = function(str, quoteChars) {
<a name="line685"></a>  var length = quoteChars.length;
<a name="line686"></a>  for (var i = 0; i &lt; length; i++) {
<a name="line687"></a>    var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);
<a name="line688"></a>    if (str.charAt(0) == quoteChar &amp;&amp; str.charAt(str.length - 1) == quoteChar) {
<a name="line689"></a>      return str.substring(1, str.length - 1);
<a name="line690"></a>    }
<a name="line691"></a>  }
<a name="line692"></a>  return str;
<a name="line693"></a>};
<a name="line694"></a>
<a name="line695"></a>
<a name="line696"></a>/**
<a name="line697"></a> * Truncates a string to a certain length and adds &#39;...&#39; if necessary.  The
<a name="line698"></a> * length also accounts for the ellipsis, so a maximum length of 10 and a string
<a name="line699"></a> * &#39;Hello World!&#39; produces &#39;Hello W...&#39;.
<a name="line700"></a> * @param {string} str The string to truncate.
<a name="line701"></a> * @param {number} chars Max number of characters.
<a name="line702"></a> * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped
<a name="line703"></a> *     characters from being cut off in the middle.
<a name="line704"></a> * @return {string} The truncated {@code str} string.
<a name="line705"></a> */
<a name="line706"></a>goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {
<a name="line707"></a>  if (opt_protectEscapedCharacters) {
<a name="line708"></a>    str = goog.string.unescapeEntities(str);
<a name="line709"></a>  }
<a name="line710"></a>
<a name="line711"></a>  if (str.length &gt; chars) {
<a name="line712"></a>    str = str.substring(0, chars - 3) + &#39;...&#39;;
<a name="line713"></a>  }
<a name="line714"></a>
<a name="line715"></a>  if (opt_protectEscapedCharacters) {
<a name="line716"></a>    str = goog.string.htmlEscape(str);
<a name="line717"></a>  }
<a name="line718"></a>
<a name="line719"></a>  return str;
<a name="line720"></a>};
<a name="line721"></a>
<a name="line722"></a>
<a name="line723"></a>/**
<a name="line724"></a> * Truncate a string in the middle, adding &quot;...&quot; if necessary,
<a name="line725"></a> * and favoring the beginning of the string.
<a name="line726"></a> * @param {string} str The string to truncate the middle of.
<a name="line727"></a> * @param {number} chars Max number of characters.
<a name="line728"></a> * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped
<a name="line729"></a> *     characters from being cutoff in the middle.
<a name="line730"></a> * @param {number=} opt_trailingChars Optional number of trailing characters to
<a name="line731"></a> *     leave at the end of the string, instead of truncating as close to the
<a name="line732"></a> *     middle as possible.
<a name="line733"></a> * @return {string} A truncated copy of {@code str}.
<a name="line734"></a> */
<a name="line735"></a>goog.string.truncateMiddle = function(str, chars,
<a name="line736"></a>    opt_protectEscapedCharacters, opt_trailingChars) {
<a name="line737"></a>  if (opt_protectEscapedCharacters) {
<a name="line738"></a>    str = goog.string.unescapeEntities(str);
<a name="line739"></a>  }
<a name="line740"></a>
<a name="line741"></a>  if (opt_trailingChars &amp;&amp; str.length &gt; chars) {
<a name="line742"></a>    if (opt_trailingChars &gt; chars) {
<a name="line743"></a>      opt_trailingChars = chars;
<a name="line744"></a>    }
<a name="line745"></a>    var endPoint = str.length - opt_trailingChars;
<a name="line746"></a>    var startPoint = chars - opt_trailingChars;
<a name="line747"></a>    str = str.substring(0, startPoint) + &#39;...&#39; + str.substring(endPoint);
<a name="line748"></a>  } else if (str.length &gt; chars) {
<a name="line749"></a>    // Favor the beginning of the string:
<a name="line750"></a>    var half = Math.floor(chars / 2);
<a name="line751"></a>    var endPos = str.length - half;
<a name="line752"></a>    half += chars % 2;
<a name="line753"></a>    str = str.substring(0, half) + &#39;...&#39; + str.substring(endPos);
<a name="line754"></a>  }
<a name="line755"></a>
<a name="line756"></a>  if (opt_protectEscapedCharacters) {
<a name="line757"></a>    str = goog.string.htmlEscape(str);
<a name="line758"></a>  }
<a name="line759"></a>
<a name="line760"></a>  return str;
<a name="line761"></a>};
<a name="line762"></a>
<a name="line763"></a>
<a name="line764"></a>/**
<a name="line765"></a> * Special chars that need to be escaped for goog.string.quote.
<a name="line766"></a> * @private
<a name="line767"></a> * @type {Object}
<a name="line768"></a> */
<a name="line769"></a>goog.string.specialEscapeChars_ = {
<a name="line770"></a>  &#39;\0&#39;: &#39;\\0&#39;,
<a name="line771"></a>  &#39;\b&#39;: &#39;\\b&#39;,
<a name="line772"></a>  &#39;\f&#39;: &#39;\\f&#39;,
<a name="line773"></a>  &#39;\n&#39;: &#39;\\n&#39;,
<a name="line774"></a>  &#39;\r&#39;: &#39;\\r&#39;,
<a name="line775"></a>  &#39;\t&#39;: &#39;\\t&#39;,
<a name="line776"></a>  &#39;\x0B&#39;: &#39;\\x0B&#39;, // &#39;\v&#39; is not supported in JScript
<a name="line777"></a>  &#39;&quot;&#39;: &#39;\\&quot;&#39;,
<a name="line778"></a>  &#39;\\&#39;: &#39;\\\\&#39;
<a name="line779"></a>};
<a name="line780"></a>
<a name="line781"></a>
<a name="line782"></a>/**
<a name="line783"></a> * Character mappings used internally for goog.string.escapeChar.
<a name="line784"></a> * @private
<a name="line785"></a> * @type {Object}
<a name="line786"></a> */
<a name="line787"></a>goog.string.jsEscapeCache_ = {
<a name="line788"></a>  &#39;\&#39;&#39;: &#39;\\\&#39;&#39;
<a name="line789"></a>};
<a name="line790"></a>
<a name="line791"></a>
<a name="line792"></a>/**
<a name="line793"></a> * Encloses a string in double quotes and escapes characters so that the
<a name="line794"></a> * string is a valid JS string.
<a name="line795"></a> * @param {string} s The string to quote.
<a name="line796"></a> * @return {string} A copy of {@code s} surrounded by double quotes.
<a name="line797"></a> */
<a name="line798"></a>goog.string.quote = function(s) {
<a name="line799"></a>  s = String(s);
<a name="line800"></a>  if (s.quote) {
<a name="line801"></a>    return s.quote();
<a name="line802"></a>  } else {
<a name="line803"></a>    var sb = [&#39;&quot;&#39;];
<a name="line804"></a>    for (var i = 0; i &lt; s.length; i++) {
<a name="line805"></a>      var ch = s.charAt(i);
<a name="line806"></a>      var cc = ch.charCodeAt(0);
<a name="line807"></a>      sb[i + 1] = goog.string.specialEscapeChars_[ch] ||
<a name="line808"></a>          ((cc &gt; 31 &amp;&amp; cc &lt; 127) ? ch : goog.string.escapeChar(ch));
<a name="line809"></a>    }
<a name="line810"></a>    sb.push(&#39;&quot;&#39;);
<a name="line811"></a>    return sb.join(&#39;&#39;);
<a name="line812"></a>  }
<a name="line813"></a>};
<a name="line814"></a>
<a name="line815"></a>
<a name="line816"></a>/**
<a name="line817"></a> * Takes a string and returns the escaped string for that character.
<a name="line818"></a> * @param {string} str The string to escape.
<a name="line819"></a> * @return {string} An escaped string representing {@code str}.
<a name="line820"></a> */
<a name="line821"></a>goog.string.escapeString = function(str) {
<a name="line822"></a>  var sb = [];
<a name="line823"></a>  for (var i = 0; i &lt; str.length; i++) {
<a name="line824"></a>    sb[i] = goog.string.escapeChar(str.charAt(i));
<a name="line825"></a>  }
<a name="line826"></a>  return sb.join(&#39;&#39;);
<a name="line827"></a>};
<a name="line828"></a>
<a name="line829"></a>
<a name="line830"></a>/**
<a name="line831"></a> * Takes a character and returns the escaped string for that character. For
<a name="line832"></a> * example escapeChar(String.fromCharCode(15)) -&gt; &quot;\\x0E&quot;.
<a name="line833"></a> * @param {string} c The character to escape.
<a name="line834"></a> * @return {string} An escaped string representing {@code c}.
<a name="line835"></a> */
<a name="line836"></a>goog.string.escapeChar = function(c) {
<a name="line837"></a>  if (c in goog.string.jsEscapeCache_) {
<a name="line838"></a>    return goog.string.jsEscapeCache_[c];
<a name="line839"></a>  }
<a name="line840"></a>
<a name="line841"></a>  if (c in goog.string.specialEscapeChars_) {
<a name="line842"></a>    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];
<a name="line843"></a>  }
<a name="line844"></a>
<a name="line845"></a>  var rv = c;
<a name="line846"></a>  var cc = c.charCodeAt(0);
<a name="line847"></a>  if (cc &gt; 31 &amp;&amp; cc &lt; 127) {
<a name="line848"></a>    rv = c;
<a name="line849"></a>  } else {
<a name="line850"></a>    // tab is 9 but handled above
<a name="line851"></a>    if (cc &lt; 256) {
<a name="line852"></a>      rv = &#39;\\x&#39;;
<a name="line853"></a>      if (cc &lt; 16 || cc &gt; 256) {
<a name="line854"></a>        rv += &#39;0&#39;;
<a name="line855"></a>      }
<a name="line856"></a>    } else {
<a name="line857"></a>      rv = &#39;\\u&#39;;
<a name="line858"></a>      if (cc &lt; 4096) { // \u1000
<a name="line859"></a>        rv += &#39;0&#39;;
<a name="line860"></a>      }
<a name="line861"></a>    }
<a name="line862"></a>    rv += cc.toString(16).toUpperCase();
<a name="line863"></a>  }
<a name="line864"></a>
<a name="line865"></a>  return goog.string.jsEscapeCache_[c] = rv;
<a name="line866"></a>};
<a name="line867"></a>
<a name="line868"></a>
<a name="line869"></a>/**
<a name="line870"></a> * Takes a string and creates a map (Object) in which the keys are the
<a name="line871"></a> * characters in the string. The value for the key is set to true. You can
<a name="line872"></a> * then use goog.object.map or goog.array.map to change the values.
<a name="line873"></a> * @param {string} s The string to build the map from.
<a name="line874"></a> * @return {Object} The map of characters used.
<a name="line875"></a> */
<a name="line876"></a>// TODO(arv): It seems like we should have a generic goog.array.toMap. But do
<a name="line877"></a>//            we want a dependency on goog.array in goog.string?
<a name="line878"></a>goog.string.toMap = function(s) {
<a name="line879"></a>  var rv = {};
<a name="line880"></a>  for (var i = 0; i &lt; s.length; i++) {
<a name="line881"></a>    rv[s.charAt(i)] = true;
<a name="line882"></a>  }
<a name="line883"></a>  return rv;
<a name="line884"></a>};
<a name="line885"></a>
<a name="line886"></a>
<a name="line887"></a>/**
<a name="line888"></a> * Checks whether a string contains a given substring.
<a name="line889"></a> * @param {string} s The string to test.
<a name="line890"></a> * @param {string} ss The substring to test for.
<a name="line891"></a> * @return {boolean} True if {@code s} contains {@code ss}.
<a name="line892"></a> */
<a name="line893"></a>goog.string.contains = function(s, ss) {
<a name="line894"></a>  return s.indexOf(ss) != -1;
<a name="line895"></a>};
<a name="line896"></a>
<a name="line897"></a>
<a name="line898"></a>/**
<a name="line899"></a> * Returns the non-overlapping occurrences of ss in s.
<a name="line900"></a> * If either s or ss evalutes to false, then returns zero.
<a name="line901"></a> * @param {string} s The string to look in.
<a name="line902"></a> * @param {string} ss The string to look for.
<a name="line903"></a> * @return {number} Number of occurrences of ss in s.
<a name="line904"></a> */
<a name="line905"></a>goog.string.countOf = function(s, ss) {
<a name="line906"></a>  return s &amp;&amp; ss ? s.split(ss).length - 1 : 0;
<a name="line907"></a>};
<a name="line908"></a>
<a name="line909"></a>
<a name="line910"></a>/**
<a name="line911"></a> * Removes a substring of a specified length at a specific
<a name="line912"></a> * index in a string.
<a name="line913"></a> * @param {string} s The base string from which to remove.
<a name="line914"></a> * @param {number} index The index at which to remove the substring.
<a name="line915"></a> * @param {number} stringLength The length of the substring to remove.
<a name="line916"></a> * @return {string} A copy of {@code s} with the substring removed or the full
<a name="line917"></a> *     string if nothing is removed or the input is invalid.
<a name="line918"></a> */
<a name="line919"></a>goog.string.removeAt = function(s, index, stringLength) {
<a name="line920"></a>  var resultStr = s;
<a name="line921"></a>  // If the index is greater or equal to 0 then remove substring
<a name="line922"></a>  if (index &gt;= 0 &amp;&amp; index &lt; s.length &amp;&amp; stringLength &gt; 0) {
<a name="line923"></a>    resultStr = s.substr(0, index) +
<a name="line924"></a>        s.substr(index + stringLength, s.length - index - stringLength);
<a name="line925"></a>  }
<a name="line926"></a>  return resultStr;
<a name="line927"></a>};
<a name="line928"></a>
<a name="line929"></a>
<a name="line930"></a>/**
<a name="line931"></a> *  Removes the first occurrence of a substring from a string.
<a name="line932"></a> *  @param {string} s The base string from which to remove.
<a name="line933"></a> *  @param {string} ss The string to remove.
<a name="line934"></a> *  @return {string} A copy of {@code s} with {@code ss} removed or the full
<a name="line935"></a> *      string if nothing is removed.
<a name="line936"></a> */
<a name="line937"></a>goog.string.remove = function(s, ss) {
<a name="line938"></a>  var re = new RegExp(goog.string.regExpEscape(ss), &#39;&#39;);
<a name="line939"></a>  return s.replace(re, &#39;&#39;);
<a name="line940"></a>};
<a name="line941"></a>
<a name="line942"></a>
<a name="line943"></a>/**
<a name="line944"></a> *  Removes all occurrences of a substring from a string.
<a name="line945"></a> *  @param {string} s The base string from which to remove.
<a name="line946"></a> *  @param {string} ss The string to remove.
<a name="line947"></a> *  @return {string} A copy of {@code s} with {@code ss} removed or the full
<a name="line948"></a> *      string if nothing is removed.
<a name="line949"></a> */
<a name="line950"></a>goog.string.removeAll = function(s, ss) {
<a name="line951"></a>  var re = new RegExp(goog.string.regExpEscape(ss), &#39;g&#39;);
<a name="line952"></a>  return s.replace(re, &#39;&#39;);
<a name="line953"></a>};
<a name="line954"></a>
<a name="line955"></a>
<a name="line956"></a>/**
<a name="line957"></a> * Escapes characters in the string that are not safe to use in a RegExp.
<a name="line958"></a> * @param {*} s The string to escape. If not a string, it will be casted
<a name="line959"></a> *     to one.
<a name="line960"></a> * @return {string} A RegExp safe, escaped copy of {@code s}.
<a name="line961"></a> */
<a name="line962"></a>goog.string.regExpEscape = function(s) {
<a name="line963"></a>  return String(s).replace(/([-()\[\]{}+?*.$\^|,:#&lt;!\\])/g, &#39;\\$1&#39;).
<a name="line964"></a>      replace(/\x08/g, &#39;\\x08&#39;);
<a name="line965"></a>};
<a name="line966"></a>
<a name="line967"></a>
<a name="line968"></a>/**
<a name="line969"></a> * Repeats a string n times.
<a name="line970"></a> * @param {string} string The string to repeat.
<a name="line971"></a> * @param {number} length The number of times to repeat.
<a name="line972"></a> * @return {string} A string containing {@code length} repetitions of
<a name="line973"></a> *     {@code string}.
<a name="line974"></a> */
<a name="line975"></a>goog.string.repeat = function(string, length) {
<a name="line976"></a>  return new Array(length + 1).join(string);
<a name="line977"></a>};
<a name="line978"></a>
<a name="line979"></a>
<a name="line980"></a>/**
<a name="line981"></a> * Pads number to given length and optionally rounds it to a given precision.
<a name="line982"></a> * For example:
<a name="line983"></a> * &lt;pre&gt;padNumber(1.25, 2, 3) -&gt; &#39;01.250&#39;
<a name="line984"></a> * padNumber(1.25, 2) -&gt; &#39;01.25&#39;
<a name="line985"></a> * padNumber(1.25, 2, 1) -&gt; &#39;01.3&#39;
<a name="line986"></a> * padNumber(1.25, 0) -&gt; &#39;1.25&#39;&lt;/pre&gt;
<a name="line987"></a> *
<a name="line988"></a> * @param {number} num The number to pad.
<a name="line989"></a> * @param {number} length The desired length.
<a name="line990"></a> * @param {number=} opt_precision The desired precision.
<a name="line991"></a> * @return {string} {@code num} as a string with the given options.
<a name="line992"></a> */
<a name="line993"></a>goog.string.padNumber = function(num, length, opt_precision) {
<a name="line994"></a>  var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num);
<a name="line995"></a>  var index = s.indexOf(&#39;.&#39;);
<a name="line996"></a>  if (index == -1) {
<a name="line997"></a>    index = s.length;
<a name="line998"></a>  }
<a name="line999"></a>  return goog.string.repeat(&#39;0&#39;, Math.max(0, length - index)) + s;
<a name="line1000"></a>};
<a name="line1001"></a>
<a name="line1002"></a>
<a name="line1003"></a>/**
<a name="line1004"></a> * Returns a string representation of the given object, with
<a name="line1005"></a> * null and undefined being returned as the empty string.
<a name="line1006"></a> *
<a name="line1007"></a> * @param {*} obj The object to convert.
<a name="line1008"></a> * @return {string} A string representation of the {@code obj}.
<a name="line1009"></a> */
<a name="line1010"></a>goog.string.makeSafe = function(obj) {
<a name="line1011"></a>  return obj == null ? &#39;&#39; : String(obj);
<a name="line1012"></a>};
<a name="line1013"></a>
<a name="line1014"></a>
<a name="line1015"></a>/**
<a name="line1016"></a> * Concatenates string expressions. This is useful
<a name="line1017"></a> * since some browsers are very inefficient when it comes to using plus to
<a name="line1018"></a> * concat strings. Be careful when using null and undefined here since
<a name="line1019"></a> * these will not be included in the result. If you need to represent these
<a name="line1020"></a> * be sure to cast the argument to a String first.
<a name="line1021"></a> * For example:
<a name="line1022"></a> * &lt;pre&gt;buildString(&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;) -&gt; &#39;abcd&#39;
<a name="line1023"></a> * buildString(null, undefined) -&gt; &#39;&#39;
<a name="line1024"></a> * &lt;/pre&gt;
<a name="line1025"></a> * @param {...*} var_args A list of strings to concatenate. If not a string,
<a name="line1026"></a> *     it will be casted to one.
<a name="line1027"></a> * @return {string} The concatenation of {@code var_args}.
<a name="line1028"></a> */
<a name="line1029"></a>goog.string.buildString = function(var_args) {
<a name="line1030"></a>  return Array.prototype.join.call(arguments, &#39;&#39;);
<a name="line1031"></a>};
<a name="line1032"></a>
<a name="line1033"></a>
<a name="line1034"></a>/**
<a name="line1035"></a> * Returns a string with at least 64-bits of randomness.
<a name="line1036"></a> *
<a name="line1037"></a> * Doesn&#39;t trust Javascript&#39;s random function entirely. Uses a combination of
<a name="line1038"></a> * random and current timestamp, and then encodes the string in base-36 to
<a name="line1039"></a> * make it shorter.
<a name="line1040"></a> *
<a name="line1041"></a> * @return {string} A random string, e.g. sn1s7vb4gcic.
<a name="line1042"></a> */
<a name="line1043"></a>goog.string.getRandomString = function() {
<a name="line1044"></a>  var x = 2147483648;
<a name="line1045"></a>  return Math.floor(Math.random() * x).toString(36) +
<a name="line1046"></a>         Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);
<a name="line1047"></a>};
<a name="line1048"></a>
<a name="line1049"></a>
<a name="line1050"></a>/**
<a name="line1051"></a> * Compares two version numbers.
<a name="line1052"></a> *
<a name="line1053"></a> * @param {string|number} version1 Version of first item.
<a name="line1054"></a> * @param {string|number} version2 Version of second item.
<a name="line1055"></a> *
<a name="line1056"></a> * @return {number}  1 if {@code version1} is higher.
<a name="line1057"></a> *                   0 if arguments are equal.
<a name="line1058"></a> *                  -1 if {@code version2} is higher.
<a name="line1059"></a> */
<a name="line1060"></a>goog.string.compareVersions = function(version1, version2) {
<a name="line1061"></a>  var order = 0;
<a name="line1062"></a>  // Trim leading and trailing whitespace and split the versions into
<a name="line1063"></a>  // subversions.
<a name="line1064"></a>  var v1Subs = goog.string.trim(String(version1)).split(&#39;.&#39;);
<a name="line1065"></a>  var v2Subs = goog.string.trim(String(version2)).split(&#39;.&#39;);
<a name="line1066"></a>  var subCount = Math.max(v1Subs.length, v2Subs.length);
<a name="line1067"></a>
<a name="line1068"></a>  // Iterate over the subversions, as long as they appear to be equivalent.
<a name="line1069"></a>  for (var subIdx = 0; order == 0 &amp;&amp; subIdx &lt; subCount; subIdx++) {
<a name="line1070"></a>    var v1Sub = v1Subs[subIdx] || &#39;&#39;;
<a name="line1071"></a>    var v2Sub = v2Subs[subIdx] || &#39;&#39;;
<a name="line1072"></a>
<a name="line1073"></a>    // Split the subversions into pairs of numbers and qualifiers (like &#39;b&#39;).
<a name="line1074"></a>    // Two different RegExp objects are needed because they are both using
<a name="line1075"></a>    // the &#39;g&#39; flag.
<a name="line1076"></a>    var v1CompParser = new RegExp(&#39;(\\d*)(\\D*)&#39;, &#39;g&#39;);
<a name="line1077"></a>    var v2CompParser = new RegExp(&#39;(\\d*)(\\D*)&#39;, &#39;g&#39;);
<a name="line1078"></a>    do {
<a name="line1079"></a>      var v1Comp = v1CompParser.exec(v1Sub) || [&#39;&#39;, &#39;&#39;, &#39;&#39;];
<a name="line1080"></a>      var v2Comp = v2CompParser.exec(v2Sub) || [&#39;&#39;, &#39;&#39;, &#39;&#39;];
<a name="line1081"></a>      // Break if there are no more matches.
<a name="line1082"></a>      if (v1Comp[0].length == 0 &amp;&amp; v2Comp[0].length == 0) {
<a name="line1083"></a>        break;
<a name="line1084"></a>      }
<a name="line1085"></a>
<a name="line1086"></a>      // Parse the numeric part of the subversion. A missing number is
<a name="line1087"></a>      // equivalent to 0.
<a name="line1088"></a>      var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);
<a name="line1089"></a>      var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);
<a name="line1090"></a>
<a name="line1091"></a>      // Compare the subversion components. The number has the highest
<a name="line1092"></a>      // precedence. Next, if the numbers are equal, a subversion without any
<a name="line1093"></a>      // qualifier is always higher than a subversion with any qualifier. Next,
<a name="line1094"></a>      // the qualifiers are compared as strings.
<a name="line1095"></a>      order = goog.string.compareElements_(v1CompNum, v2CompNum) ||
<a name="line1096"></a>          goog.string.compareElements_(v1Comp[2].length == 0,
<a name="line1097"></a>              v2Comp[2].length == 0) ||
<a name="line1098"></a>          goog.string.compareElements_(v1Comp[2], v2Comp[2]);
<a name="line1099"></a>      // Stop as soon as an inequality is discovered.
<a name="line1100"></a>    } while (order == 0);
<a name="line1101"></a>  }
<a name="line1102"></a>
<a name="line1103"></a>  return order;
<a name="line1104"></a>};
<a name="line1105"></a>
<a name="line1106"></a>
<a name="line1107"></a>/**
<a name="line1108"></a> * Compares elements of a version number.
<a name="line1109"></a> *
<a name="line1110"></a> * @param {string|number|boolean} left An element from a version number.
<a name="line1111"></a> * @param {string|number|boolean} right An element from a version number.
<a name="line1112"></a> *
<a name="line1113"></a> * @return {number}  1 if {@code left} is higher.
<a name="line1114"></a> *                   0 if arguments are equal.
<a name="line1115"></a> *                  -1 if {@code right} is higher.
<a name="line1116"></a> * @private
<a name="line1117"></a> */
<a name="line1118"></a>goog.string.compareElements_ = function(left, right) {
<a name="line1119"></a>  if (left &lt; right) {
<a name="line1120"></a>    return -1;
<a name="line1121"></a>  } else if (left &gt; right) {
<a name="line1122"></a>    return 1;
<a name="line1123"></a>  }
<a name="line1124"></a>  return 0;
<a name="line1125"></a>};
<a name="line1126"></a>
<a name="line1127"></a>
<a name="line1128"></a>/**
<a name="line1129"></a> * Maximum value of #goog.string.hashCode, exclusive. 2^32.
<a name="line1130"></a> * @type {number}
<a name="line1131"></a> * @private
<a name="line1132"></a> */
<a name="line1133"></a>goog.string.HASHCODE_MAX_ = 0x100000000;
<a name="line1134"></a>
<a name="line1135"></a>
<a name="line1136"></a>/**
<a name="line1137"></a> * String hash function similar to java.lang.String.hashCode().
<a name="line1138"></a> * The hash code for a string is computed as
<a name="line1139"></a> * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
<a name="line1140"></a> * where s[i] is the ith character of the string and n is the length of
<a name="line1141"></a> * the string. We mod the result to make it between 0 (inclusive) and 2^32
<a name="line1142"></a> * (exclusive).
<a name="line1143"></a> * @param {string} str A string.
<a name="line1144"></a> * @return {number} Hash value for {@code str}, between 0 (inclusive) and 2^32
<a name="line1145"></a> *  (exclusive). The empty string returns 0.
<a name="line1146"></a> */
<a name="line1147"></a>goog.string.hashCode = function(str) {
<a name="line1148"></a>  var result = 0;
<a name="line1149"></a>  for (var i = 0; i &lt; str.length; ++i) {
<a name="line1150"></a>    result = 31 * result + str.charCodeAt(i);
<a name="line1151"></a>    // Normalize to 4 byte range, 0 ... 2^32.
<a name="line1152"></a>    result %= goog.string.HASHCODE_MAX_;
<a name="line1153"></a>  }
<a name="line1154"></a>  return result;
<a name="line1155"></a>};
<a name="line1156"></a>
<a name="line1157"></a>
<a name="line1158"></a>/**
<a name="line1159"></a> * The most recent unique ID. |0 is equivalent to Math.floor in this case.
<a name="line1160"></a> * @type {number}
<a name="line1161"></a> * @private
<a name="line1162"></a> */
<a name="line1163"></a>goog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;
<a name="line1164"></a>
<a name="line1165"></a>
<a name="line1166"></a>/**
<a name="line1167"></a> * Generates and returns a string which is unique in the current document.
<a name="line1168"></a> * This is useful, for example, to create unique IDs for DOM elements.
<a name="line1169"></a> * @return {string} A unique id.
<a name="line1170"></a> */
<a name="line1171"></a>goog.string.createUniqueString = function() {
<a name="line1172"></a>  return &#39;goog_&#39; + goog.string.uniqueStringCounter_++;
<a name="line1173"></a>};
<a name="line1174"></a>
<a name="line1175"></a>
<a name="line1176"></a>/**
<a name="line1177"></a> * Converts the supplied string to a number, which may be Ininity or NaN.
<a name="line1178"></a> * This function strips whitespace: (toNumber(&#39; 123&#39;) === 123)
<a name="line1179"></a> * This function accepts scientific notation: (toNumber(&#39;1e1&#39;) === 10)
<a name="line1180"></a> *
<a name="line1181"></a> * This is better than Javascript&#39;s built-in conversions because, sadly:
<a name="line1182"></a> *     (Number(&#39; &#39;) === 0) and (parseFloat(&#39;123a&#39;) === 123)
<a name="line1183"></a> *
<a name="line1184"></a> * @param {string} str The string to convert.
<a name="line1185"></a> * @return {number} The number the supplied string represents, or NaN.
<a name="line1186"></a> */
<a name="line1187"></a>goog.string.toNumber = function(str) {
<a name="line1188"></a>  var num = Number(str);
<a name="line1189"></a>  if (num == 0 &amp;&amp; goog.string.isEmpty(str)) {
<a name="line1190"></a>    return NaN;
<a name="line1191"></a>  }
<a name="line1192"></a>  return num;
<a name="line1193"></a>};
<a name="line1194"></a>
<a name="line1195"></a>
<a name="line1196"></a>/**
<a name="line1197"></a> * Converts a string from selector-case to camelCase (e.g. from
<a name="line1198"></a> * &quot;multi-part-string&quot; to &quot;multiPartString&quot;), useful for converting
<a name="line1199"></a> * CSS selectors and HTML dataset keys to their equivalent JS properties.
<a name="line1200"></a> * @param {string} str The string in selector-case form.
<a name="line1201"></a> * @return {string} The string in camelCase form.
<a name="line1202"></a> */
<a name="line1203"></a>goog.string.toCamelCase = function(str) {
<a name="line1204"></a>  return String(str).replace(/\-([a-z])/g, function(all, match) {
<a name="line1205"></a>    return match.toUpperCase();
<a name="line1206"></a>  });
<a name="line1207"></a>};
<a name="line1208"></a>
<a name="line1209"></a>
<a name="line1210"></a>/**
<a name="line1211"></a> * Converts a string from camelCase to selector-case (e.g. from
<a name="line1212"></a> * &quot;multiPartString&quot; to &quot;multi-part-string&quot;), useful for converting JS
<a name="line1213"></a> * style and dataset properties to equivalent CSS selectors and HTML keys.
<a name="line1214"></a> * @param {string} str The string in camelCase form.
<a name="line1215"></a> * @return {string} The string in selector-case form.
<a name="line1216"></a> */
<a name="line1217"></a>goog.string.toSelectorCase = function(str) {
<a name="line1218"></a>  return String(str).replace(/([A-Z])/g, &#39;-$1&#39;).toLowerCase();
<a name="line1219"></a>};
<a name="line1220"></a>
<a name="line1221"></a>
<a name="line1222"></a>/**
<a name="line1223"></a> * Converts a string into TitleCase. First character of the string is always
<a name="line1224"></a> * capitalized in addition to the first letter of every subsequent word.
<a name="line1225"></a> * Words are delimited by one or more whitespaces by default. Custom delimiters
<a name="line1226"></a> * can optionally be specified to replace the default, which doesn&#39;t preserve
<a name="line1227"></a> * whitespace delimiters and instead must be explicitly included if needed.
<a name="line1228"></a> *
<a name="line1229"></a> * Default delimiter =&gt; &quot; &quot;:
<a name="line1230"></a> *    goog.string.toTitleCase(&#39;oneTwoThree&#39;)    =&gt; &#39;OneTwoThree&#39;
<a name="line1231"></a> *    goog.string.toTitleCase(&#39;one two three&#39;)  =&gt; &#39;One Two Three&#39;
<a name="line1232"></a> *    goog.string.toTitleCase(&#39;  one   two   &#39;) =&gt; &#39;  One   Two   &#39;
<a name="line1233"></a> *    goog.string.toTitleCase(&#39;one_two_three&#39;)  =&gt; &#39;One_two_three&#39;
<a name="line1234"></a> *    goog.string.toTitleCase(&#39;one-two-three&#39;)  =&gt; &#39;One-two-three&#39;
<a name="line1235"></a> *
<a name="line1236"></a> * Custom delimiter =&gt; &quot;_-.&quot;:
<a name="line1237"></a> *    goog.string.toTitleCase(&#39;oneTwoThree&#39;, &#39;_-.&#39;)       =&gt; &#39;OneTwoThree&#39;
<a name="line1238"></a> *    goog.string.toTitleCase(&#39;one two three&#39;, &#39;_-.&#39;)     =&gt; &#39;One two three&#39;
<a name="line1239"></a> *    goog.string.toTitleCase(&#39;  one   two   &#39;, &#39;_-.&#39;)    =&gt; &#39;  one   two   &#39;
<a name="line1240"></a> *    goog.string.toTitleCase(&#39;one_two_three&#39;, &#39;_-.&#39;)     =&gt; &#39;One_Two_Three&#39;
<a name="line1241"></a> *    goog.string.toTitleCase(&#39;one-two-three&#39;, &#39;_-.&#39;)     =&gt; &#39;One-Two-Three&#39;
<a name="line1242"></a> *    goog.string.toTitleCase(&#39;one...two...three&#39;, &#39;_-.&#39;) =&gt; &#39;One...Two...Three&#39;
<a name="line1243"></a> *    goog.string.toTitleCase(&#39;one. two. three&#39;, &#39;_-.&#39;)   =&gt; &#39;One. two. three&#39;
<a name="line1244"></a> *    goog.string.toTitleCase(&#39;one-two.three&#39;, &#39;_-.&#39;)     =&gt; &#39;One-Two.Three&#39;
<a name="line1245"></a> *
<a name="line1246"></a> * @param {string} str String value in camelCase form.
<a name="line1247"></a> * @param {string=} opt_delimiters Custom delimiter character set used to
<a name="line1248"></a> *      distinguish words in the string value. Each character represents a
<a name="line1249"></a> *      single delimiter. When provided, default whitespace delimiter is
<a name="line1250"></a> *      overridden and must be explicitly included if needed.
<a name="line1251"></a> * @return {string} String value in TitleCase form.
<a name="line1252"></a> */
<a name="line1253"></a>goog.string.toTitleCase = function(str, opt_delimiters) {
<a name="line1254"></a>  var delimiters = goog.isString(opt_delimiters) ?
<a name="line1255"></a>      goog.string.regExpEscape(opt_delimiters) : &#39;\\s&#39;;
<a name="line1256"></a>
<a name="line1257"></a>  // For IE8, we need to prevent using an empty character set. Otherwise,
<a name="line1258"></a>  // incorrect matching will occur.
<a name="line1259"></a>  delimiters = delimiters ? &#39;|[&#39; + delimiters + &#39;]+&#39; : &#39;&#39;;
<a name="line1260"></a>
<a name="line1261"></a>  var regexp = new RegExp(&#39;(^&#39; + delimiters + &#39;)([a-z])&#39;, &#39;g&#39;);
<a name="line1262"></a>  return str.replace(regexp, function(all, p1, p2) {
<a name="line1263"></a>    return p1 + p2.toUpperCase();
<a name="line1264"></a>  });
<a name="line1265"></a>};
<a name="line1266"></a>
<a name="line1267"></a>
<a name="line1268"></a>/**
<a name="line1269"></a> * Parse a string in decimal or hexidecimal (&#39;0xFFFF&#39;) form.
<a name="line1270"></a> *
<a name="line1271"></a> * To parse a particular radix, please use parseInt(string, radix) directly. See
<a name="line1272"></a> * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt
<a name="line1273"></a> *
<a name="line1274"></a> * This is a wrapper for the built-in parseInt function that will only parse
<a name="line1275"></a> * numbers as base 10 or base 16.  Some JS implementations assume strings
<a name="line1276"></a> * starting with &quot;0&quot; are intended to be octal. ES3 allowed but discouraged
<a name="line1277"></a> * this behavior. ES5 forbids it.  This function emulates the ES5 behavior.
<a name="line1278"></a> *
<a name="line1279"></a> * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj
<a name="line1280"></a> *
<a name="line1281"></a> * @param {string|number|null|undefined} value The value to be parsed.
<a name="line1282"></a> * @return {number} The number, parsed. If the string failed to parse, this
<a name="line1283"></a> *     will be NaN.
<a name="line1284"></a> */
<a name="line1285"></a>goog.string.parseInt = function(value) {
<a name="line1286"></a>  // Force finite numbers to strings.
<a name="line1287"></a>  if (isFinite(value)) {
<a name="line1288"></a>    value = String(value);
<a name="line1289"></a>  }
<a name="line1290"></a>
<a name="line1291"></a>  if (goog.isString(value)) {
<a name="line1292"></a>    // If the string starts with &#39;0x&#39; or &#39;-0x&#39;, parse as hex.
<a name="line1293"></a>    return /^\s*-?0x/i.test(value) ?
<a name="line1294"></a>        parseInt(value, 16) : parseInt(value, 10);
<a name="line1295"></a>  }
<a name="line1296"></a>
<a name="line1297"></a>  return NaN;
<a name="line1298"></a>};
</pre>


</body>
</html>
